<?php
/**
 * Scrittura su file temporaneo dell'array dati importreqtype serializzato
 * e redirect alla pagina confronto / importreqtype
 */
function tabExport($aReqExp){
	global $objSDAO;
	$aExpTab = array();
	//load expTab array
	foreach($aReqExp as $z1 => $aReq) {
		$msg = loadExpTab($aReq[0], $aReq[1], $aExpTab );
		if ($msg != '') { return $msg; } 
	}
	//dbg_("export ".print_r($aExpTab,1));
	//crea dir temp
 	if (!is_dir(SERVER_FS_TEMP."/imex")) {
 		mkdir(SERVER_FS_TEMP."/imex",0775);
 	}
 	if ($dh = opendir(SERVER_FS_TEMP."/imex")) { //delete file temp 2 days old
 		$ymdLimit = date('ymd',time()-3600*48);
	  	while ($file = readdir($dh)) {
	      if (substr($file,0,3)=='exp' and substr($file,3,6)< $ymdLimit) {
	      	unlink(SERVER_FS_TEMP."/imex/".$file);
	      }
	   }
	   closedir($dh);
	}
 	
 	if (!is_dir(SERVER_FS_TEMP."/imex")) {
 		return _t("Unable to create directory %s",SERVER_FS_TEMP."/imex");
 	}
 	// create  file-name and file-header
 	$nomeFile = 'exp'.uniqid(date('ymd'));
	$sFileHeader = str_pad("POLARIS-MB ".date("Y-m-d H:i:s")." ".$objSDAO->dbcPar['dbcType']." ".
		$objSDAO->dbcPar['host']." ".$objSDAO->dbcPar['dbName']." ".
		$_SERVER['SERVER_NAME']." ".$_ENV['COMPUTERNAME'],128);
 	$serTab = serialize($aExpTab);
	if(!file_put_contents(SERVER_FS_TEMP."/imex/$nomeFile.txt", $sFileHeader.$serTab)) {
 		return _t("Impossibile creare il file %s",SERVER_FS_TEMP."/imex/$nomeFile.txt");
	}
	//dbg_("aExpTab=".print_r($aExpTab,1));
	// redirect to apge compare / export
	serverRedir(SERVER_URL_ROOT."/app/util/imex/exportMB.php?nf=$nomeFile&xsn=".XSN);
	return "???";
}

/**
 * load parent and children item and related in importa-data array
 */
function loadExpTab($tabRef, $keyRef, &$aExpTab ) {
 	global $objSDAO;
 	if (str_replace('@','',$keyRef)=='') { //empty key - ignore
 		return '';
 	}
 	if (isset($aExpTab[$tabRef][$keyRef])) { // loaded yet
 		return '';
 	}
 	$qz = "`";
	// INCLUDE $aStructMB and $aDependence
	$aStructMB = array();
	include(SERVER_FS_ROOT."/app/util/imex/_inc/aStructMB.const.php");
	$aDependence = array();
	include(SERVER_FS_ROOT."/app/util/imex/_inc/impExpDependence.const.php");
	// export main reference table
	if (!isset($aStructMB[$tabRef])) {
		return _t("Main table %s not defined in aStructMB.const",$tabRef)."<br>";
	}
	// crete where SQL for parent-key and key attribute array
	$aKV = explode('@',$keyRef);
	$sCondRefer = '';
	$sep = '';
	$aNomiKeyRef = array();
	foreach($aStructMB[$tabRef] as $k => $nomeKey) {
		if (!isset($aKV[$k])) {
			return _t("Table=%s key=%s - missing item n.%s (exp.ref.)",$tabRef,$keyRef,$k+1)."<br>";
		}
		if ($aKV[$k]=='') {return '';} //key attrib. empty => no export
		$sCondRefer .= $sep.$qz.$nomeKey.$qz." = '".sxAS($aKV[$k])."'";
		$sep = " AND ";
		$aNomiKeyRef[] = $nomeKey;
	}
	// read parent
	$sSQL = "SELECT * FROM `$tabRef` WHERE $sCondRefer";
	//dbg_($sSQL);
	$objSDAO->query($sSQL,'tab');
	if(!$row=$objSDAO->fetch('tab')) {
		return _t("Tabella %s - chiave '%s' inesistente (%s) (exp.ref.)",$tabRef,$keyRef,$sCondRefer)."<br>";
	}
	$aExpTab[$tabRef][$keyRef]['r']=$row;
	$aReqExp = array();
	if (isset($aRelation[$tabRef])) {
		foreach($aRelation[$tabRef] as $tabRel => $aKeyRel) {
			$keyValRel = $sep = '';
			foreach($aKeyRel as $nome1 => $nome2) {
				$keyValRel .= $sep.$row[$nome1];
				$sep = '@';
			}
			$aReqExp[] = array($tabRel,$keyValRel);
		}
	}
	// if dipendencies, scan them
	if (isset($aDependence[$tabRef])) {
		//dbg_("Keys:".print_r($aDependence[$tabRef],1));
		// children export	
		foreach($aDependence[$tabRef] as $z1 => $tab) {
			if (!isset($aStructMB[$tab])) {
				return _t("Table referenced %s not defined in aStructMB.const",$tab)."<br>";
			}
			//$aExpTab[$tabRef][$keyRef]['c'][$tab] = array();
			// read children
			$sSQL = "SELECT * FROM `$tab` WHERE $sCondRefer";
			//dbg_($sSQL);
			$objSDAO->query($sSQL,'tab');
			while($row=$objSDAO->fetch('tab')) {
				// prepare children keys (@ separator)
				$sKey = $sep = '';
				foreach($aStructMB[$tab] as $z5 => $nk) {
					if (!isset($row[$nk])) {
						return _t("Primary key %s.%s defined in strutMB.const doesn't exist",$tab,$nk)."<br>";
					}
					$sKey .= $sep.$row[$nk];
					$sep = '@';
				}
				//if dependencies - recall dipendencies manager
				if (isset($aDependence[$tab])) {
					$aReqExp[] = array($tab,$sKey);
				} else { // else load them
					$aExpTab[$tabRef][$keyRef]['c'][$tab][$sKey]=$row;
				}
				// if relationship load request array
				if (isset($aRelation[$tab])) {
					foreach($aRelation[$tab] as $tabRel => $aKeyRel) {
						$keyValRel = $sep = '';
						foreach($aKeyRel as $nome1 => $nome2) {
							$keyValRel .= $sep.$row[$nome1];
							$sep = '@';
						}
						$aReqExp[] = array($tabRel,$keyValRel);
					}
				}
			}
		}
	}
	//dbg_("$tabRef aReqExp=".print_r($aReqExp,1));
	// load to exporting data array for entities whith dipendencies and relationship
	foreach($aReqExp as $z3 => $aReq) {
		$msg = loadExpTab($aReq[0], $aReq[1], $aExpTab );
		if ($msg != '') { return $msg; } 
	}
	return '';
}

/**
 * compare items (parent and children) of data-array with current meta-base
 */
function tabCompare(&$aTabImp){
 	global $objSDAO;
 	$qz = "`";
	$aCompTab = array();
	// include DI $aStructMB
	$aStructMB = array();
	require(SERVER_FS_ROOT."/app/util/imex/_inc/aStructMB.const.php");
	$aDependence = array();
	require(SERVER_FS_ROOT."/app/util/imex/_inc/impExpDependence.const.php");
	// scorre l'array dati importreqtype
	foreach($aTabImp as $tabRef => $aTR) {
		if (!isset($aStructMB[$tabRef])) {
			return _t("Table '%s' not defined in strutMB.const",$tabRef)."<br>";
		}
		foreach($aTR as $keyRef => $aTabCR) {
			// costruisce chiave padre (referente principale)
			$xKV = explode('@',$keyRef);
			$sCondRefer = $sep = '';
			$aNomiKeyRef = $aStructMB[$tabRef];			
			foreach($aNomiKeyRef as $k => $nomeKey) {
				if (!isset($xKV[$k])) {
					return _t("Tabella=%s chiave=%s - manca elemento n.%s (conf.tab.)",$tabRef,$keyRef,$k+1)."<br>";
				}
				$sCondRefer .= $sep.$qz.$nomeKey.$qz." = '".sxAS($xKV[$k])."'";
				$sep = " AND ";
			}
			// confronta padre
			$aDiff = diffTab($tabRef, array($aTabCR['r']), $aNomiKeyRef, $sCondRefer, $aStructMB);
			$aCompTab[$tabRef][$keyRef][$tabRef] = $aDiff;
			// scorre figli
			if (isset($aTabCR['c'])) {
				foreach($aTabCR['c'] as $tab => $aRec) {
					// confronta figlio
					$aDiff = diffTab($tab, $aRec, $aNomiKeyRef, $sCondRefer, $aStructMB);
					if (count($aDiff) > 0) {
						$aCompTab[$tabRef][$keyRef][$tab] = $aDiff;
					}
				}
			}
		}
	}
	return $aCompTab;
}

/**
 * confronta singola tabella
 */
function diffTab($tab, $aRec, $aNomiKeyRef, $sCondRefer, &$aStructMB) {
 	global $objSDAO;
 	$qz = "`";
	$aDiff = array();
	$aKeyImp = array();
	// scorre array records
	foreach($aRec as $z1 => $recImp) {
		//dbg_("recImp:".print_r($recImp,1));
		// costruisce chiave
		$cond = $sep = '';
		$aCampiKeyImp = array();
		foreach($aStructMB[$tab] as $z2 => $nomePK) {
			if (!isset($recImp[$nomePK])) {
				return _t("Primary key %s.%s defined in strutMB.const not exists",$tab,$nomePK)."<br>";
			}
			$cond .= $sep.$qz.$nomePK.$qz." = '".sxAS($recImp[$nomePK])."'";
			$sep = " AND ";
			$aCampiKeyImp[$nomePK] = $recImp[$nomePK];
		}
		// legge record meta-base corrente
		$sSQL = "SELECT * FROM `$tab` WHERE $cond";
		$objSDAO->query($sSQL,'tab');
		//dbg_($sSQL);
		if (!$rowCorr=$objSDAO->fetch('tab')) { // non esiste su MB corr -> nuovo record
			$sKey = $sep = '';
			foreach($aCampiKeyImp as $nom => $val) {
				$sKey .= $sep.$val;
				$sep = '@';
			}
			$aDiff[$sKey] = array('op'=>'ins','var'=>array());
			continue;
		}
		//dbg_("rowCorr:".print_r($rowCorr,1));
		// per il confronto serializza gli array record ordinati su nome campo
		ksort($recImp);
		ksort($rowCorr);
		if (serialize($rowCorr) != serialize($recImp)) { //record diversi
			$sKey = $sep = '';
			foreach($aCampiKeyImp as $nom => $val) {
				$sKey .= $sep.$val;
				$sep = '@';
			}
			$aDiff[$sKey]['op'] = 'mod';
			// visualizza campi differenti
			foreach($rowCorr as $nom => $valCorr) {
				if ($recImp[$nom] != $valCorr) {
					$aDiff[$sKey]['var'][] = "$nom : '".
						((strlen($valCorr)>20)?substr($valCorr,0,20).'...':$valCorr)."' diventa '".
						((strlen($recImp[$nom])>20)?substr($recImp[$nom],0,20).'...':$recImp[$nom])."'<br>";
				}
			}
		}
		// memorizza chiave per verifica rec. camcellati
		$aKeyImp[] = serialize($aCampiKeyImp);
	}
	// controlla cancellati - legge tutti i record e segnala quelli non presente in $aKeyImp
	$sSQL = "SELECT * FROM `$tab` WHERE $sCondRefer";
	//dbg_($sSQL);
	$objSDAO->query($sSQL,'tab');
	while($rowCorr=$objSDAO->fetch('tab')) {
		$aCampiKeyMB = array();
		foreach($aStructMB[$tab] as $z4 => $nomePK) {
			if (!isset($rowCorr[$nomePK])) {
				return _t("Primary key $tab.$nomePK defined in strutMB.const not exists on current meta-base")."<br>";
			}
			$aCampiKeyMB[$nomePK] = $rowCorr[$nomePK];
		}
		$sKeyMB = serialize($aCampiKeyMB);
		if (!in_array($sKeyMB, $aKeyImp)) { // chiave cancellata
			$sKey = $sep = '';
			foreach($aCampiKeyMB as $nom => $val) {
				$sKey .= $sep.$val;
				$sep = '@';
			}
			$aDiff[$sKey] = array('op'=>'del','var'=>array());
		}
	}
	return $aDiff;
} // fine diffTab

/**
 * Aggiorna meta-base corrente con dati array dati importreqtype relativamente alle chiavi passate in aKeyVar
 */
function tabImport(&$aTabImp, $aKeyVar){
 	global $objSDAO;
 	dbg_($aTabImp);
 	$qz = "`";
	// include $aDependence e $aStructMB
	$aStructMB = array();
	require(SERVER_FS_ROOT."/app/util/imex/_inc/aStructMB.const.php");
	$aDependence = array();
	require(SERVER_FS_ROOT."/app/util/imex/_inc/impExpDependence.const.php");
	//dbg_("tabImport - aTabImp=".print_r($aTabImp,1));
	//dbg_("tabImport - aKeyVar=".print_r($aKeyVar,1));
	// scorre array dati importreqtype
	foreach($aTabImp as $tabRef => $aTR) {
		if (!isset($aStructMB[$tabRef])) {
			return _t("Table $tabRef not defined in strutMB.const")."<br>";
		}
		foreach($aTR as $keyRef => $aTabCR) {
			// costruisce chiave padre (referente principale)
			$xKV = explode('@',$keyRef);
			$sCondRefer = $sep = '';
			$aNomiKeyRef = $aStructMB[$tabRef];			
			foreach($aNomiKeyRef as $k => $nomeKey) {
				if (!isset($xKV[$k])) {
					return _t("Tabella=%s chiave=%s - manca elemento n.%s (imp.ref.)",$tabRef,$keyRef,$k+1)."<br>";
				}
				$sCondRefer .= $sep.$qz.$nomeKey.$qz." = '".sxAS($xKV[$k])."'";
				$sep = " AND ";
			}
			//dbg_("tabref=$tabRef keyref=$keyRef");
			// se chiave presente in aKeyVar esegue la relativa operreqtype
			if (isset($aKeyVar[$tabRef][$keyRef])) {
				if ($aKeyVar[$tabRef][$keyRef] == 'del') {
					// cancellreqtype 
					$sSQL = "DELETE FROM `$tabRef` WHERE $sCondRefer";
					$objSDAO->exec($sSQL);
				} elseif ($aKeyVar[$tabRef][$keyRef] == 'mod') {
					// modifica 
					$sSQL = "UPDATE `$tabRef` SET ";
					$sep = '';
					foreach($aTabCR['r'] as $nom => $val) {
						$sSQL .= $sep.$qz.$nom.$qz." = '".sxAS($val)."'";
						$sep = ',';
					}
					$sSQL .= " WHERE $sCondRefer";
					//dbg_("tabref=$tabRef keyref=$keyRef - $sSQL");
					$objSDAO->exec($sSQL);
				} else {
					//inserimento
					$sSQL = "INSERT INTO $tabRef (";
					$sep = '';
					foreach($aTabCR['r'] as $nom => $val) {
						$sSQL .= $sep.$qz.$nom.$qz;
						$sep = ',';
					}
					$sSQL .= ") VALUES ('";
					$sep = '';
					foreach($aTabCR['r'] as $nom => $val) {
						$sSQL .= $sep.sxAS($val);
						$sep = "','";
					}
					$sSQL .= "')";
					$objSDAO->exec($sSQL);
				}
			}
			// scorre l'array figli
			if (!isset($aTabCR['c'])) { continue; }
			foreach($aTabCR['c'] as $tab => $aRecImp) {
				foreach($aRecImp as $keyImp => $recImp) {
					if (!isset($aStructMB[$tab])) {
						return _t("Table $tab not defined in strutMB.const")."<br>";
					}
					// costruisce la chiave e controlla congruenza con chiave tab
					$sCond = $sep = '';
					$xKV = explode('@',$keyImp);
					foreach($aStructMB[$tab] as $k => $nomeKey) {
						if (!isset($xKV[$k])) {
							return _t("Tabella=%s chiave=%s - manca elemento n.%s (imp.tab.)",$tab,$nomeKey,$k+1)."<br>";
						}
						$sCond .= $sep.$qz.$nomeKey.$qz." = '".sxAS($recImp[$nomeKey])."'";
						$sep = " AND ";
					}
					//dbg_("--- tab=$tab keyImp=$keyImp");
					// se chiave presente in aKeyVar esegue la relativa operreqtype
					if (isset($aKeyVar[$tab][$keyImp])) {
						if ($aKeyVar[$tab][$keyImp] == 'mod') {
							// modifica 
							$sSQL = "UPDATE `$tab` SET ";
							$sep = '';
							foreach($recImp as $nom => $val) {
								$sSQL .= $sep.$qz.$nom.$qz." = '".sxAS($val)."'";
								$sep = ',';
							}
							$sSQL .= " WHERE $sCond";
							$objSDAO->exec($sSQL);
						} 
						if ($aKeyVar[$tab][$keyImp] == 'ins') {
							// inserimento
							$sSQL = "INSERT INTO `$tab` (";
							$sep = '';
							foreach($recImp as $nom => $val) {
								$sSQL .= $sep.$qz.$nom.$qz;
								$sep = ',';
							}
							$sSQL .= ") VALUES ('";
							$sep = '';
							foreach($recImp as $nom => $val) {
								$sSQL .= $sep.sxAS($val);
								$sep = "','";
							}
							$sSQL .= "')";
							$objSDAO->exec($sSQL);
						}
					}
				}
			}
		}
	}
	foreach($aKeyVar as $tab => $aKeyImp ) {
		foreach($aKeyImp as $keyImp => $oper) {
			if ($oper == 'del') {
				// costruisce la chiave
				$sCond = $sep = '';
				$xKV = explode('@',$keyImp);
				foreach($aStructMB[$tab] as $k => $nomeKey) {
					if (!isset($xKV[$k])) {
						return _t("Tabella=%s chiave=%s - manca elemento n.%s (imp.tab.)",$tab,$nomeKey,$k+1)."<br>";
					}
					$sCond .= $sep.$qz.$nomeKey.$qz." = '".sxAS($xKV[$k])."'";
					$sep = " AND ";
				}
				// cancellreqtype 
				$sSQL = "DELETE FROM `$tab` WHERE $sCond";
				//dbg_("--- tab=$tab keyref=$keyImp - $sSQL");
				$objSDAO->exec($sSQL);
			}
		}
	}
	return '';
}

?>
